/*
 * @Author: master
 * @Date: 2022-04-08 13:18:01
 * @LastEditTime: 2024-07-25 10:47:18
 * @Description: 插件服务
 */
import vue from '@vitejs/plugin-vue'; // Vue3 单文件组件支持
import vueJsx from '@vitejs/plugin-vue-jsx'; // Vue3 JSX 支持
import { createHtmlPlugin } from 'vite-plugin-html'; // 增加 EJS 标签
import viteCompression from 'vite-plugin-compression'; // 系统命令，压缩服务
import Components from 'unplugin-vue-components/vite'; // 开启按需加载的支持
import AutoImport from 'unplugin-auto-import/vite'; // 自动导入
import { ArcoResolver, VantResolver } from 'unplugin-vue-components/resolvers'; // 按需加载（模板）arco和vant
import styleImport from 'vite-plugin-style-import'; // 按需加载
import viteImagemin from 'vite-plugin-imagemin'; // 压缩图片插件
import viteCesiumPlugin from '../viteHook/viteCesiumPlugin.js'; // cesium 插件钩子
import viteStaticPlugin from '../viteHook/viteStaticPlugin.js'; //
import viteHookPlugin from '../viteHook/viteHookPlugin.js'; // vite的通用钩子
import viteMockPlugin from '../viteHook/viteMockPlugin.js'; // vite mock服务钩子
import hytdStyleResolve from './hytd-style-plugin.js'; // 组件库按需引入css插件
import topLevelAwait from 'vite-plugin-top-level-await'; // 顶级await语法支持
import eslintPlugin from '@nabla/vite-plugin-eslint'; // 后台执行eslint编辑执行
import basicSsl from '@vitejs/plugin-basic-ssl';
import legacy from '@vitejs/plugin-legacy'; // 低版本兼容
import requireTransform from 'vite-plugin-require-transform';
import commonjs from 'vite-plugin-commonjs';
/**
 * 获取plugins
 * @param {Object} viteConfig vite的自定义配置
 * @returns {Array} plugins
 */
export default function plugins(viteConfig) {
  /**
   * 设置项目中的config文件
   */
  const setProjectConfig = () => {
    // 开发模式
    if (viteConfig.nodeEnv === 'dev') {
      return `<script src="/config/system.${viteConfig.nodeEnv}.config.js"></script>`;
    }
    // 打包模式
    else {
      return `<script src="${viteConfig.base}config/system.config.js?v=${Date.now()}"></script>`;
    }
  };
  /**
   * 插入主入口文件
   */
  const setMainInjectScript = () => {
    if (viteConfig.nodeEnv === 'dev') {
      return `<script type="module" src="${
        viteConfig.nginx_proxy_pass === true
          ? `http://${viteConfig.ipAddress}:${viteConfig.port}${viteConfig.base}`
          : './'
      }index.${viteConfig.injectType === 'ts' ? 'ts' : 'js'}"></script>`;
    } else {
      return `<script type="module" src="./index.${viteConfig.injectType === 'ts' ? 'ts' : 'js'}"></script>`;
    }
  };
  // 插件集合
  const plugins = [
    // Vue3 单文件组件支持
    vue(),
    // Vue3 JSX 支持
    vueJsx(),
    // 增加 EJS 标签
    createHtmlPlugin({
      minify: true,
      /**
       * 需要注入 index.html ejs 模版的数据
       */
      inject: {
        data: {
          // 根据mode模式设置项目的config文件
          injectConfigScript: setProjectConfig(),
          // 插入入口文件，‘nginx_proxy_pass’是开启可以通过nginx代理转发的方式进行访问的方式，默认是关闭的
          injectScript: setMainInjectScript(),
        },
        // tags: [
        //   {
        //     injectTo: 'body-prepend',
        //     tag: 'div',
        //     attrs: {
        //       id: 'tag',
        //     },
        //   },
        // ],
      },
    }),
    // 顶层 await 语法支持
    topLevelAwait({
      promiseExportName: '__tla',
      promiseImportName: i => `__tla_${i}`,
    }),
    // 后台代码检查
    eslintPlugin(),
    legacy({
      targets: ['defaults', 'ie >= 11', 'chrome 52'], // 需要兼容的目标列表，可以设置多个
      additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
      renderLegacyChunks: true,
      polyfills: [
        'es.symbol',
        'es.array.filter',
        'es.promise',
        'es.promise.finally',
        'es/map',
        'es/set',
        'es.array.for-each',
        'es.object.define-properties',
        'es.object.define-property',
        'es.object.get-own-property-descriptor',
        'es.object.get-own-property-descriptors',
        'es.object.keys',
        'es.object.to-string',
        'web.dom-collections.for-each',
        'esnext.global-this',
        'esnext.string.match-all',
      ],
    }),
    requireTransform({
      fileRegex: /.js$|.vue$/,
    }),
    commonjs(),
  ];
  // 地图3d模式
  if (viteConfig?.map && viteConfig.map === '3d') {
    // cesium 插件钩子
    plugins.push(viteCesiumPlugin(viteConfig));
  }
  // plugins.push(viteStaticPlugin(viteConfig));
  // 按需引入
  lazyImportPlugin(plugins, viteConfig);
  // 图片服务
  imagePlugin(plugins, viteConfig);
  // vite的通用钩子
  if (viteConfig.nodeEnv === 'prod') {
    plugins.push(viteHookPlugin(viteConfig));
  }
  // vite mock服务钩子
  if (viteConfig.nodeEnv === 'dev') {
    plugins.push(viteMockPlugin(viteConfig));
  }
  // 开启了https
  if (viteConfig.https === true) {
    plugins.push(basicSsl());
  }
  return plugins;
}
/**
 * 按需引入插件
 */
const lazyImportPlugin = (plugins, viteConfig) => {
  // 按需加载style配置
  const styleImportOptions = {
    libs: [],
    resolves: [
      // 自有vue3.0组件库，组件库style按需引入
      ...hytdStyleResolve(),
    ],
  };
  // 开启按需加载
  if (viteConfig.lazyImport === true) {
    // 模板引入
    const resolvers = [];
    // 样式引入
    // 移动端
    if (viteConfig.application === 'mobile') {
      styleImportOptions.libs.push({
        libraryName: 'vant',
        esModule: true,
        resolveStyle: name => {
          return `../es/${name}/style/index.mjs`;
        },
      });
      // vant移动端按需引入
      resolvers.push(VantResolver());
    } else {
      plugins.push(
        AutoImport({
          resolvers: [
            ArcoResolver({
              sideEffect: true,
            }),
          ],
        }),
      );
      // arco design模板按需引入
      resolvers.push(
        ArcoResolver({
          sideEffect: true,
        }),
      );
    }
    plugins.push(
      // 开启按需加载的支持
      Components({
        resolvers,
      }),
    );
  }
  plugins.push(
    // 按需加载样式文件
    styleImport(styleImportOptions),
  );
  return plugins;
};
/**
 * 图片插件
 */
const imagePlugin = (plugins, viteConfig) => {
  if (viteConfig.nodeEnv === 'prod') {
    plugins.push(
      // 压缩服务
      viteCompression({
        filename: '[path].gz[query]',
        algorithm: 'gzip',
        test: /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i,
      }),
      // 压缩图片插件
      viteImagemin({
        gifsicle: {
          optimizationLevel: 7,
          interlaced: false,
        },
        optipng: {
          optimizationLevel: 7,
        },
        mozjpeg: {
          quality: 20,
        },
        pngquant: {
          quality: [0.8, 0.9],
          speed: 4,
        },
        svgo: {
          plugins: [
            {
              name: 'removeViewBox',
            },
            {
              name: 'removeEmptyAttrs',
              active: false,
            },
          ],
        },
      }),
    );
  }
};
